package ext.vpde.cadvaulting.util;

// java imports
import java.io.*;
import java.util.*;
import java.sql.*;

//windchill imports
import com.ptc.core.htmlcomp.gathering.*;
import com.ptc.windchill.cadx.common.util.ObjectDependentsList;
import wt.access.*;
import wt.admin.*;
import wt.fc.collections.WTCollection;
import wt.content.*;
import wt.enterprise.RevisionControlled;
import wt.epm.*;
import wt.epm.workspaces.EPMAsStoredConfigSpec;
import wt.fc.*;
import wt.fc.collections.*;
import wt.iba.definition.URLDefinition;
import wt.iba.definition.litedefinition.*;
import wt.iba.definition.service.*;
import wt.iba.value.litevalue.*;
import wt.iba.value.*;
import wt.inf.container.*;
import wt.lifecycle.*;
import wt.locks.LockException;
import wt.maturity.*;
import wt.org.WTPrincipal;
import wt.pds.DatabaseInfoUtilities;
import wt.query.SearchCondition;
import wt.query.QuerySpec;
import wt.rule.init.*;
import wt.session.*;
import wt.vc.*;
import wt.vc.wip.Workable;
import wt.queue.*;
import wt.util.*;
import wt.vc.wip.*;


public class WpHelperUtility
{
	public static final boolean VERBOSE;
    private static final String WTHOME;
	   static {
	      try {
	         WTProperties properties = WTProperties.getLocalProperties();
	         VERBOSE = properties.getProperty("ext.vpde.cadvaulting.verbose", false);
	         WTHOME = properties.getProperty("wt.home", "");

	      }
	      catch (Throwable t)
	      {
	         System.err.println("Error initializing ");
	         t.printStackTrace(System.err);
	         throw new ExceptionInInitializerError(t);
	      }
   }

    public static String mapVersion(String version)
        throws Exception
    {
		if (VERBOSE) System.out.println("inside mapVersion");
		Connection connection = DBAccess.getConnection();
        Statement stmt = connection.createStatement();
        String query = "select STANDARDVERSION from ZVERSIONMAP where LEGACYVERSION='"+version+"\'";
        ResultSet rs= stmt.executeQuery(query);
        String standardversion=null;
        while (rs.next())
        {
			standardversion = rs.getString("STANDARDVERSION");
			System.out.println("standardversion: " + standardversion);
		}
		if (VERBOSE) System.out.println("mapping version: " + version + " to '" + standardversion);
		return (standardversion==null)?version:standardversion;
    }

   /***
    * setVersion changes the version of an object in the datastore based on the mapping table ZVERSIONMAP
    * calls inner class WpVersionHelper to launch asynchronous thread waiting for release of record
    * - VersionControlService locks record until standard revision sequence is completed
    ***/

   public static void setVersion( Versioned target, String table ) throws WTException
   {
	   //if (!isStandard(target))
	   //{
		   final WpVersionHelper vh = new WpVersionHelper((Versioned)target, table);
		   new Thread(
			   new Runnable()
			   {
				   public void run()
				   {
					   try{vh.setVersion();}catch(Exception e){e.printStackTrace();}
				   }
			   }
		   ).start();
	   //}
	   //setOIRLifecycle( (LifeCycleManaged)target);
   }

   /***
    * standardVersion determines whether the versioning scheme associated with the given object
    * is part of the standard scheme as identified in the table ZVERSIONMAP
    ***/
    public static boolean isStandard(Versioned target)
    {
		boolean standard = false;
		try
		{
			String version = ((Versioned)target).getVersionIdentifier().getValue();
			if (VERBOSE) System.out.println("Checking if standard: " + version);
			Connection connection = DBAccess.getConnection();
			Statement stmt = connection.createStatement();
			String query = "select IS_STANDARD from ZVERSIONMAP where LEGACYVERSION='"+version+"\'";
			ResultSet rs= stmt.executeQuery(query);
			while (rs.next())
			{
				standard = rs.getBoolean("IS_STANDARD");
				System.out.println("is standard version: " + standard);
			}
	    }catch(SQLException e){e.printStackTrace();}
	    return (standard);
    }

   protected static void setState( LifeCycleManaged the_lifecycle_managed, String state ) throws WTException {
         try {
            if(state!=null) {
                 String current_user = wt.session.SessionMgr.getPrincipal().getName();
                 String admin_user = wt.admin.AdministrativeDomainHelper.ADMINISTRATOR_NAME;
                 boolean is_admin = admin_user.equals(current_user);
               if(!is_admin) {
                  changePrincipal(admin_user);
                  System.out.println("\nSwitching user to Administrator (Setting lifecycle state...)");
               }
               try {
                  LifeCycleServerHelper.setState(the_lifecycle_managed,State.toState(state));
               }
               finally {
                  if(!is_admin) {
                     changePrincipal(current_user);
                     System.out.println("\nSwitching user from Administrator (...lifecycle state set)");
                  }
               }
            }
         }
         catch ( WTPropertyVetoException e ) {
           System.out.println("\nsetState: " + e.getMessage());
           e.printStackTrace();
           throw new WTException(e);
         }
   }

   public static void setOIRLifecycle( LifeCycleManaged object) throws WTException {
         try {
			 WTContainerRef context = ((WTContained)object).getContainerReference();
			 LifeCycleTemplateReference lctRef = (LifeCycleTemplateReference)InitRuleHelper.evaluator.getValue("lifeCycle.id", object, context);;
                if(VERBOSE){
					System.out.println("Reassigning " + ((WTObject)object).getDisplayIdentity() + " to lifecycle " + lctRef.getName());
				}
			 object = LifeCycleHelper.service.reassign(object, lctRef);
         }
         catch ( Exception e ) {
           e.printStackTrace();
           throw new WTException(e);
         }
   }

    public static void changePrincipal(String s)
        throws WTException
    {
        try
        {
            String s1 = SessionMgr.getPrincipal().getName();
            if(s == null || s.equals(""))
            {
                if(VERBOSE)
                    System.out.println((new StringBuilder()).append("Use default principal of ").append(s1).toString());
            } else
            if(!s1.equals(s))
            {
                if(VERBOSE)
                    System.out.println((new StringBuilder()).append("Attempting to change principal to <").append(s).append(">").toString());
                SessionMgr.setPrincipal(s);
                String s2 = SessionMgr.getPrincipal().getName();
                System.out.println("");
            } else
            if(VERBOSE)
                System.out.println((new StringBuilder()).append("Principal already set to ").append(s).toString());
        }
        catch(WTException wtexception)
        {
            System.err.println((new StringBuilder()).append("unable to get/set principal").append(wtexception).toString());
            throw new WTException();
        }
    }


    /***
     *  This section contains common methods for getting information/creating object instances
     *
     ***/
    public static WTObject getObject(String obid)
        throws WTException
    {
        if(obid == null)
            throw new WTException("WARNING!!! OBID NULL");
        obid = obid.trim();

        try
        {
			ReferenceFactory rf = new ReferenceFactory();
			WTReference ref = rf.getReference(obid);
		    WTObject object = (WTObject) ref.getObject();
		    if(object == null)
		      throw new Exception("Invalid obid, unable to instantiate object");
		    else
              return object;
        }
        catch(Exception exception)
        {
            exception.printStackTrace();
            throw new WTException(exception);
        }
    }
    public static final WTContainerRef getTargetContainer(String containerPath)
        throws WTException
    {
		WTContainerRef wtcontainerref;
		wtcontainerref = WTContainerHelper.service.getByPath(containerPath);
        if(wtcontainerref != null) return wtcontainerref;
        if(wtcontainerref == null)
        {
            System.out.println("WARNING: INVALID CONTAINER REFERENCE!");
            wtcontainerref = WTContainerHelper.service.getClassicRef();
        }
        return wtcontainerref;
	}

    public static Workable getCheckOutObject( Workable workable, String note ) throws LockException, WTException {
     Workable retVal = null;
     try {
        if(WorkInProgressHelper.service.isCheckoutAllowed(workable)) {
           WorkInProgressHelper.service.checkout(workable,WorkInProgressHelper.service.getCheckoutFolder(),note);
           retVal = WorkInProgressHelper.service.workingCopyOf(workable);
        }
     }
     catch ( Exception e ) {
        e.printStackTrace();
        throw new WTException(e.getMessage());
     }
     if(retVal==null) throw new WTException("Checkout Failed!");
     return retVal;
    }

    public static Workable checkInObject( Workable workable, String note ) throws LockException, WTException {
		Workable retVal = null;
		try {
			if(WorkInProgressHelper.isCheckedOut(workable)) {
				retVal = WorkInProgressHelper.service.checkin(workable,note);
			}
		}
		catch ( Exception e ) {
			e.printStackTrace();
			throw new WTException(e.getMessage());
		}
		if(retVal==null) throw new WTException("Checkin Failed!");
		return retVal;
	}

 /**************************************************************************
  * Name:        validateDependents
  *
  * Purpose:
  *
  **************************************************************************
  */
 public static Vector validateDependents (PromotionNotice promotionNotice)throws Exception {
	   if (VERBOSE) System.out.println("*** validating Promotion Notice: " + ((WTObject)promotionNotice).getDisplayIdentity() );
	   Vector<String> result = new Vector<String>(2);
	   //StringBuffer is message returned to calling method
	   StringBuffer sb = new StringBuffer();
	   //find target associated to Promotion Notice
	   QueryResult qr_targets = MaturityHelper.service.getPromotionTargets(promotionNotice);
	   //fatal error occurs when target is not latest iteration in branch
	   boolean fatal_error = false;

	   EPMDocument drawing;
	   WTObject object;
	   WTHashSet collection = new WTHashSet();
	   while (qr_targets.hasMoreElements()){
		   object = (WTObject)qr_targets.nextElement();
		   if (isCADDrawing(object)){
			   drawing = (EPMDocument)object;
			   collection.add(drawing);
			   EPMAsStoredConfigSpec configspec = EPMAsStoredConfigSpec.newEPMAsStoredConfigSpec(drawing);
			   DependencyHelper dephelper = new DependencyHelper(collection, configspec, null);
			   //collection = (WTHashSet)dephelper.getRequiredDependents(epmdocument);
			   collection = (WTHashSet)dephelper.getAllDependents(wt.epm.EPMDocument.class);
			   Iterator iterator = collection.iterator();
			   while(iterator.hasNext())
			   {
				   ObjectReference ref = (ObjectReference)iterator.next();
				   object = (WTObject)( ref.getObject() );
				   if (object instanceof EPMDocument){
					   if (VERBOSE) System.out.println("*** validating dependent: " + object.getDisplayIdentity() );
					   if (!VersionControlHelper.isLatestIteration((Iterated)object)){
						   fatal_error = true;
					       sb.append("FATAL ERROR:").append(object.getDisplayIdentity()).append(" not latest iteration\n");
					   }
					   if (!isLatestVersion((Versioned)object)){
						   sb.append("WARNING:").append(object.getDisplayIdentity()).append(" not latest version\n");
					   }
				   }
			   }
		   }
	   }
	   if (VERBOSE) System.out.println(sb.toString());
	   result.add(""+fatal_error);
	   result.add(sb.toString());
	   return result;
  }

public static boolean isCADDrawing (WTObject wtobject)throws Exception {
	return (wtobject instanceof EPMDocument && (((EPMDocument)wtobject).getDocType().toString()).equals("CADDRAWING") );
}

public static boolean isLatestVersion (Versioned target)throws Exception {
	QueryResult qr = wt.vc.config.ConfigHelper.service.filteredIterationsOf(target.getMaster(), new wt.vc.config.LatestConfigSpec());
	String targetversion = VersionControlHelper.getVersionIdentifier(target).getValue();
	String latestversion = VersionControlHelper.getVersionIdentifier((Versioned)qr.nextElement()).getValue();
	return (targetversion.equals(latestversion));
}
/*********************************
//  UPLOAD CONTENT
*********************************/
    public static void uploadContent(File contentFile, ContentHolder contentholder, boolean isPrimary)
        throws WTException, FileNotFoundException, java.beans.PropertyVetoException, IOException
    {
		if ( !(contentFile.exists() && contentFile.isFile()) ) throw new WTException("***** ERROR: Cannot upload,  file does not exist ****");

		java.io.FileInputStream is = new java.io.FileInputStream(contentFile);

		ContentHolder contentcookie = ContentHelper.service.getContents(contentholder);
		wt.content.ApplicationData newAppData = wt.content.ApplicationData.newApplicationData(contentcookie);
		newAppData.setFileName( contentFile.getName() );
		System.out.println("TRACE: uploading new content file " + contentFile.getAbsolutePath() );

		if (isPrimary){
			newAppData = wt.content.ContentServerHelper.service.updatePrimary( (FormatContentHolder)contentcookie, newAppData, is);
		}else{
			newAppData = wt.content.ContentServerHelper.service.updateContent( contentcookie, newAppData, (java.io.InputStream) is);
		}
	}

/*********************************
//  UPDATE PDF URL
*********************************/
    public static void updatePdfUrl(IBAHolder ibaholder, String pdfurl, String pdflabel, String urldefname )
        throws Exception
    {
		URLValue urlvalue;
		URLDefinition urldefinition;

		QuerySpec qs = new QuerySpec(URLValue.class);
		qs.appendWhere(new SearchCondition(URLValue.class,URLValue.DESCRIPTION,SearchCondition.EQUAL,pdflabel,false));
		qs.appendAnd();
		qs.appendWhere(new SearchCondition(URLValue.class, "theIBAHolderReference.key", SearchCondition.EQUAL, PersistenceHelper.getObjectIdentifier((WTObject)ibaholder) ),0);
		QueryResult qr = PersistenceHelper.manager.find(qs);
		if (VERBOSE) System.out.println ("QueryResult for IBAValue size: " + qr.size() );

		if(qr.size() < 1) {
			System.out.println("Attribute didn't exist on object");
			qs = new QuerySpec(URLDefinition.class);
			qs.appendWhere(new SearchCondition(URLDefinition.class,URLDefinition.NAME,SearchCondition.EQUAL,urldefname,false));
			qr = PersistenceHelper.manager.find(qs);
			if ( qr.size()>0 )
			    urldefinition = (URLDefinition)qr.nextElement();
			else
		        throw new WTException("ATTRIBUTE DEFINITION \"" + urldefname + "\" DOES NOT EXIST");
			urlvalue =  URLValue.newURLValue(urldefinition, ibaholder, pdfurl, pdflabel);
		} else {
			System.out.println("Attribute already exist on object ... updating");
			System.out.println("URL = " + pdfurl);
			System.out.println("LABEL = " + pdflabel);
			urlvalue =  (URLValue)qr.nextElement();
			urlvalue.setValue(pdfurl);
			urlvalue.setDescription(pdflabel);
		}
		wt.fc.PersistenceHelper.manager.save((wt.fc.Persistable)urlvalue);
	}

	public static class WpVersionHelper
    {
        Versioned target;
        String table;

        public WpVersionHelper(Versioned versioned, String dbtable)
        {
	    	target = versioned;
	    	table = dbtable;
	    }

        public Versioned getTarget(){
	    	return target;
	    }

        public String getTable(){
	    	return table;
	    }

       public void setVersion() throws WTException
       {
	    	try
	    	{
	    		String version = ((Versioned)target).getVersionIdentifier().getValue();
	    		if (VERBOSE) System.out.println("Next Version Label: " + version);
	    		long ida2a2 = (PersistenceHelper.getObjectIdentifier((Persistable)target)).getId();
	    		String branchId = ""+((RevisionControlled)target).getBranchIdentifier();

	    		Connection connection = DBAccess.getConnection();
	    		version = mapVersion(version);
	    		if (VERBOSE) System.out.println("Table name: " + table + "\tversion: " + version + "\tida2a2: " + ida2a2);

	    		Statement stmt = connection.createStatement();
	    		// this query run as listener for release of record lock
	    		int i=0;
				String query = "UPDATE " + table + " SET VERSIONIDA2VERSIONINFO=\'" + version + "' WHERE IDA2A2="+ida2a2;
				if (VERBOSE) System.out.println("SQL: " + query);
	    		while ((stmt.executeUpdate(query))==0) i++;
				if (VERBOSE) System.out.println("DB HITS: " + i++);
	    		query = "UPDATE controlbranch SET versionid=\'" + version + "\' WHERE IDA2A2="+branchId;
	    		if (VERBOSE) System.out.println("SQL: " + query);
	    		stmt.executeUpdate(query);
	    		stmt.close();
	    		connection.close();
	    	}catch (Exception e){e.printStackTrace();}
       }
    }//end inner class WpVersionHelper
}